package cn.thrjit.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;

import cn.hutool.crypto.digest.BCrypt;
import cn.thrjit.autoconfigure.SaTokenAutoConfiguration;
import cn.thrjit.controller.manager.LoginController;
import cn.thrjit.dto.AdminLoginDto;
import cn.thrjit.dto.LoginInfoDto;
import cn.thrjit.exception.GlobalException;
import cn.thrjit.mapper.LoginMapper;
import cn.thrjit.mapper.PermissionMapper;
import cn.thrjit.pojo.domain.Login;
import cn.thrjit.pojo.domain.Permission;
import cn.thrjit.pojo.param.RegisterSaveLoginParam;
import cn.thrjit.properties.SaTokenSettingProperties;
import cn.thrjit.rocketmq.Constants;
import cn.thrjit.rocketmq.GlobalExceptionCode;
import cn.thrjit.service.ILoginService;
import cn.thrjit.template.AppWeChatTemplate;
import cn.thrjit.utils.AssertUtil;
import cn.thrjit.vo.LoginVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.security.auth.login.LoginContext;


/**
 * <p>
 * 登录表 服务实现类
 * </p>
 *
 * @author xxx
 * @since 2024-08-02
 */
@Service
public class LoginServiceImpl extends ServiceImpl<LoginMapper, Login> implements ILoginService {
    @Autowired
    private AppWeChatTemplate appWeChatTemplate;
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SaTokenSettingProperties saTokenSettingProperties;
    @Override
    @Transactional
    public LoginVO wxLogin(String code,Integer type) {
        // 获取openId，校验用户是否已注册
        String openId = appWeChatTemplate.getOpenIdByCode(code);
        // login对象
        Login login = super.getOne(new LambdaQueryWrapper<Login>() // 通过两个条件辨别出司机登录信息和乘客登录信息
                .eq(Login::getOpenId, openId)
                .eq(Login::getType, type));

        AssertUtil.isNotNull(login, GlobalExceptionCode.SERVICE_ERROR);
        Long loginId = login.getId();
        // 登录校验
        StpUtil.login(loginId);
        String tokenName = StpUtil.getTokenName();
        String tokenValue = StpUtil.getTokenValue();
        // 获取权限信息
        List<String> permission = permissionMapper.selectByLoginId(loginId);
        // 从常类类中拿到权限信息的模板，把loginId放入模板
        String key =String.format(saTokenSettingProperties.getPermissionKey(), loginId);
        // 再权限信息放入redis中
        redisTemplate.opsForValue().set(key,permission,StpUtil.getTokenTimeout(), TimeUnit.SECONDS);// 这里要注意事件单位不要写错
        // 拷贝login对象到dto对象
        LoginInfoDto loginInfoDto = BeanUtil.copyProperties(login, LoginInfoDto.class);
        // 返回登录信息
        return new LoginVO(tokenName,tokenValue,permission, loginInfoDto);
    }
    /**
     * 保存driver乘客对象
     *
     * @param
     */
    @Override
    public void saveLogin(RegisterSaveLoginParam registerSaveLoginParam) {
        Login login = new Login();
        BeanUtil.copyProperties(registerSaveLoginParam, login,false);
        login.setCreateTime(new Date());
        login.setDeleted(false);
        login.setVersion(0);
        // 设置完成后调用父类的save方法保存
        super.save(login);
    }

    /**
     * 后端登录实现
     * @param adminLoginDto
     * @return
     */
    @Override
    public LoginVO adminLogin(AdminLoginDto adminLoginDto) {
        // 参数校验
        // 业务校验：账号密码校验
        Login login = super.getOne(new LambdaQueryWrapper<Login>()
                .eq(Login::getUsername, adminLoginDto.getUsername())
                .eq(Login::getType, adminLoginDto.getType()));
        // 校验密码
        boolean checkpw = BCrypt.checkpw(adminLoginDto.getPassword(), login.getPassword());
        if (!checkpw) {
            throw new GlobalException(GlobalExceptionCode.SERVICE_ERROR);
        }
        // 业务实现使用satoken进行登录
        Long loginId = login.getId();
        StpUtil.login(loginId);
        // 通过satoken获取登录信息
        String tokenName = StpUtil.getTokenName();
        String tokenValue = StpUtil.getTokenValue();
        // 获取权限信息
        List<String> permissions = permissionMapper.selectByLoginId(loginId);
        String key =String.format(saTokenSettingProperties.getPermissionKey(), loginId);
        // 再权限信息放入redis中
        redisTemplate.opsForValue().set(key,permissions,StpUtil.getTokenTimeout(), TimeUnit.SECONDS);// 这里要注意事件单位不要写错
        // 拷贝login对象到dto对象
        LoginInfoDto loginInfoDto = BeanUtil.copyProperties(login, LoginInfoDto.class);
        return new LoginVO(tokenName,tokenValue,permissions,loginInfoDto);
    }

    /**
     * 后台账号退出登录
     */
    @Override
    public void logout() {
        String key =String.format(saTokenSettingProperties.getPermissionKey(), StpUtil.getLoginIdAsLong());
        // 需要手动把redis中的权限信息删除
        redisTemplate.delete(key);
        StpUtil.logout();


    }
}
